﻿using System;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Mirkuz.Mapping;
using Mirkuz.PowerManagement;
using Mirkuz.LocationServices;

namespace Mirkuz.TrailCompanion
{

    public partial class fMain : Mirkuz.UI.TForm
    {          
        UnattendedManager _uman = new UnattendedManager();

        Mirkuz.LocationServices.LocationProviderBase _LocationProvider;
        
        DateTime _lastfix=DateTime.Now;

        public static MapPoint CurrentPosition;
        public static TrailManager Trail = new TrailManager();
        public static WaypointManager Wpmgr = new WaypointManager();
        public static SettingDataSet settingDataSet1;

        bool _gps_ok = false;

        //fGPSStat fGPS = null;

        delegate void SimpleDelegate();

        string SettingsFileName = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/mkrunner.xml";
        string KMLFileName =Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/TC-" + DateTime.Now.ToString("yyyy-MM-dd-hh-mm") +".kml";        
        
        string applicationpath = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase) + "/";      

        public fMain() : base()
        {          
            InitializeComponent();
            
            if (Screen.PrimaryScreen.Bounds.Width == 480 && Screen.PrimaryScreen.Bounds.Height == 640)
                this.BackgroundImage = Properties.Resources.background_white_VGA;

            if (Screen.PrimaryScreen.Bounds.Width == 480 && Screen.PrimaryScreen.Bounds.Height == 800)
                this.BackgroundImage = Properties.Resources.background_white_WVGA;

            if (Screen.PrimaryScreen.Bounds.Width == 240 && Screen.PrimaryScreen.Bounds.Height == 400)
                this.BackgroundImage = Properties.Resources.background_white_WQVGA;            
        }

        private void fMain_Load(object sender, EventArgs e)
        {            
            settingDataSet1 = new Mirkuz.TrailCompanion.SettingDataSet();
            settingDataSet1.DataSetName = "SettingDataSet";
            settingDataSet1.SchemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema;
            //carico valori target
            try
            {
                settingDataSet1.ReadXml(SettingsFileName);
            }
            catch
            {
                settingDataSet1.Settings.AddSettingsRow(60,true,0,"GPSID");
                settingDataSet1.WriteXml(SettingsFileName);
            }

            if (settingDataSet1.Settings[0].GPSKind == null)
                settingDataSet1.Settings[0].GPSKind = "GPSID";

            if (settingDataSet1.Settings[0].GPSKind == "GPSID")
            {
                _LocationProvider = new LocationServices.GPSIDLocationProvider(settingDataSet1.Settings[0].GPSPolling);
            }
            else
            {
                _LocationProvider = new LocationServices.NMEAGPSLocationProvider(settingDataSet1.Settings[0].GPSKind, 4800, settingDataSet1.Settings[0].GPSPolling);
            }
            
            _LocationProvider.NewLocationAvailable += new NewLocationAvailableDelegate(_LocationProvider_NewLocationAvailable);
            _LocationProvider.DifficultReception += new DifficultReceptionDelegate(_LocationProvider_DifficultReception);          
            _LocationProvider.Start();

            tlblVersion.Text = " V:" + Assembly.GetExecutingAssembly().GetName().Version.ToString(4);            
        
        }      
       
        private void fMain_Closed(object sender, EventArgs e)
        {
            _LocationProvider.Stop();
            _LocationProvider.Dispose();
            _LocationProvider = null;

            if (Trail.IsRunning)
                Trail.Stop();

            _uman.Dispose();

        }

        #region gpsevents
        void _LocationProvider_DifficultReception(LocationProviderBase sender)
        {
            Invoke(new SimpleDelegate(DifficultReception));
        }

        void _LocationProvider_NewLocationAvailable(LocationProviderBase sender, Location l)
        {
            try
            {
                CurrentPosition = MapPoint.FromLocation(l);
                Invoke(new SimpleDelegate(UpdateData));
            }
            catch { }
        }

        private void UpdateData()
        {
            _lastfix = DateTime.Now;

            UpdateGPSUI();

            lblDIstanceToTarget.Text = "-";
            lblAltitudeToTarget.Text = "-";
            lblTarget.Text = "-";

            if (Trail.IsRunning && CurrentPosition != null)
                Trail.UpdatePosition(CurrentPosition);

            if (settingDataSet1.Settings[0].Units == (int)enUnits.enImperialUnits)
                lblDistance.Text = UnitConverter.ToMiles(Trail.RunningDistance).ToString("N2") + "mi";
            else
                lblDistance.Text = Trail.RunningDistance.ToString("N0") + " m";

            if (Trail.TargetWaypoint != null)
            {
                lblTarget.Text = Trail.TargetWaypoint.Name;

                if (settingDataSet1.Settings[0].Units == (int)enUnits.enImperialUnits)
                {
                    lblDIstanceToTarget.Text = UnitConverter.ToMiles(Trail.DistanceToTargetWaypoint).ToString("N2") + "mi";
                    lblAltitudeToTarget.Text = UnitConverter.ToFeets(Trail.AltitudeToTargetWaypoint).ToString("N0") + "ft";
                }
                else
                {
                    lblDIstanceToTarget.Text = Trail.DistanceToTargetWaypoint.ToString("N0") + " m";
                    lblAltitudeToTarget.Text = Trail.AltitudeToTargetWaypoint.ToString("N0") + " mslm";
                }
            }
        }

        private void UpdateGPSUI()
        {
            /*controlli form principale*/
            _gps_ok = false;
            tlblGPS.ForeColor = Color.Red;

            if (_LocationProvider.CurrentLocation != null)            
            {
                tlblGPS.ForeColor= Color.DarkGreen;
                try
                {
                    if (settingDataSet1.Settings[0].Units == (int)enUnits.enImperialUnits)
                    {
                        lblSpeed.Text = UnitConverter.ToMiles((_LocationProvider.CurrentLocation.Speed * 1.852) * 1000).ToString("N1") + "mph";
                        lblAltitude.Text = UnitConverter.ToFeets(_LocationProvider.CurrentLocation.Altitude).ToString("N0") + "ft";
                    }
                    else
                    {
                        lblSpeed.Text = (_LocationProvider.CurrentLocation.Speed * 1.852).ToString("N1") + " Km/h";
                        lblAltitude.Text = _LocationProvider.CurrentLocation.Altitude.ToString("N0") + " mslm";                
                    }                    
                }
                catch 
                {
                    lblAltitude.Text = "N/A";
                    lblSpeed.Text = "N/A";
                    lblAltitude.Text = "N/A";
                }

                if (_LocationProvider.CurrentLocation.HeadingValid)
                {
                    try
                    {
                        int i = (int)(_LocationProvider.CurrentLocation.Heading / 22.5f);
                        string[] headings ={"N","N-NE","NE","E-NE","E","E-SE","SE","S-SE",
                                      "S","S-SO","SO","O-SO","O","O-NO","NO","N-NO","N"};

                        lblCurHeading.Text = headings[i]
                            + " (" + _LocationProvider.CurrentLocation.Heading.ToString("N1") + "°)";

                        i = (int)(Trail.Bearing / 22.5f);
                        lblBearing.Text = headings[i]
                            + " (" + Trail.Bearing.ToString("N1") + "°)";
                    }
                    catch { lblCurHeading.Text = "N/A"; }
                }
                else
                    lblCurHeading.Text = "N/A";

                _gps_ok = true;             
            }

            /*controlli gps dettagliati*/
            //if (fGPS != null)
            //    fGPS.UpdateData(_LocationProvider.CurrentLocation);
        }

        private void DifficultReception()
        {
            tlblGPS.ForeColor= Color.Red;
            _gps_ok = false;
        }

        #endregion
       
        private void cmdStart_Click(object sender, EventArgs e)
        {
            if (Trail.IsRunning)
            {
                tmrAutoSave.Enabled = false;

                //fermo il Trail e salvo i dati
                Trail.Stop();

                _uman.ReleaseUnattendedMode();                

                Trail.SaveTrail(KMLFileName);
                mnuGmaps.Enabled = true;

                cmdStart.Text = "Start Session";

            }
            else
            {
                if (!_gps_ok)
                {
                    MessageBox.Show("No GPS Fix", "TrailCompanion", MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1);
                    return;
                }

                KMLFileName = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + "/TC-" + DateTime.Now.ToString("yyyy-MM-dd-hh-mm") + ".kml";

                //avvio il Trail
                Trail.Start(CurrentPosition);
                
                cmdStart.Text = "End Session";

                _uman.RequestUnattendedMode();

                tmrAutoSave.Enabled = settingDataSet1.Settings[0].AutosaveEnabled;
            }
        }

        #region timers
        private void tmrUpdateData_Tick(object sender, EventArgs e)
        {
            try
            {
                if (_uman.SystemState == SystemStates.On || _uman.SystemState == SystemStates.Unknown)
                    _LocationProvider.PollingTime= 10;
                else
                    _LocationProvider.PollingTime = settingDataSet1.Settings[0].GPSPolling;

                tlblGPS.Text = "GPS " + DateTime.Now.Subtract(_lastfix).TotalSeconds.ToString() + "s ago";
             
                Trail.Tick();

                lblTime.Text = Trail.ElapsedTime.Hours.ToString("00") + ":"
                                + Trail.ElapsedTime.Minutes.ToString("00") + ":"
                                + Trail.ElapsedTime.Seconds.ToString("00");               
            }
            catch { }
        }
        private void tmrAutoSave_Tick(object sender, EventArgs e)
        {
            Trail.SaveTrail(KMLFileName);
            mnuGmaps.Enabled = true;
        }
        #endregion
                
        #region menu
        private void pbIcon_Click(object sender, EventArgs e)
        {
            fAbout f = new fAbout();
            f.ShowDialog();
        }

        private void mnuAbout_Click(object sender, EventArgs e)
        {
            pbIcon_Click(sender, e);
        }

        private void mnuQuit_Click(object sender, EventArgs e)
        {
            if (!Trail.IsRunning)
            {
                this.Close();
            }
        }

        private void mnuLock_Click(object sender, EventArgs e)
        {
            VKeyManager.LockKeypad();
        }

        //private void mnuGPS_Click(object sender, EventArgs e)
        //{
        //    if (fGPS == null)
        //    {
        //        fGPS = new fGPSStat();
        //        UpdateGPSUI();
        //        fGPS.ShowDialog();
        //        fGPS.Dispose();
        //        fGPS = null;
        //    }
        //}        

        private void mnuWaypoints_Click(object sender, EventArgs e)
        {
            fWaypoints f = new fWaypoints();
            f.ShowDialog();
            f = null;
        }

        private void mnuMap_Click(object sender, EventArgs e)
        {
            try
            {
                fMap f = new fMap(Trail.Track);
                f.ShowDialog();
                f.Dispose();
                f = null;
            }
            catch { }
        }
        private void mnuSettings_Click(object sender, EventArgs e)
        {
            try
            {
                fSettings f = new fSettings();
                if (f.ShowDialog() == DialogResult.OK)
                {                    
                    //salvataggio settings
                    settingDataSet1.Settings[0].GPSPolling = int.Parse(f.tcmbPolling.SelectedItem.Value);
                    settingDataSet1.Settings[0].GPSKind = f.tcmbGPSKind.SelectedItem.Value;
                    settingDataSet1.Settings[0].AutosaveEnabled = (f.tcmbAutosave.SelectedItem.Value == "yes")? true:false;
                    settingDataSet1.Settings[0].Units = int.Parse(f.tcmbMetricImperial.SelectedItem.Value);
                    tmrAutoSave.Enabled = settingDataSet1.Settings[0].AutosaveEnabled;
                    settingDataSet1.WriteXml(SettingsFileName);
                }

                f.Dispose();
                f = null;
            }
            catch { }
        }

        private void mnuGmaps_Click(object sender, EventArgs e)
        {
            try
            {
                if (Trail.IsRunning)
                    Trail.SaveTrail(KMLFileName);
           
                if (System.IO.File.Exists(KMLFileName)) 
                    System.Diagnostics.Process.Start(KMLFileName, "");                                    
                 
            }catch
            {
                MessageBox.Show("Error while launching GoogleMaps", "TrailCompanion", MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1);
            }
        }
        #endregion        

       


    }
}